//! # 增强的 Prometheus 集成模块
//!
//! 提供企业级的 Prometheus 指标导出功能，包括：
//! * 标准 `/metrics` HTTP 端点
//! * 自定义指标注册
//! * 指标聚合和采样
//! * 性能优化的指标收集
//! * 与 Spring Boot Actuator 兼容的指标格式

use crate::collector::{MetricsCollector, MetricFamily, MetricType, MetricValue, Labels, Metric};
use async_trait::async_trait;
use axum::{
    extract::State,
    http::{HeaderMap, HeaderValue, StatusCode},
    response::{IntoResponse, Response},
    routing::get,
    Router,
};
use rustcloud_core::{ServiceResult, ServiceError};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Write;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;
use tracing::{debug, error, info, warn};

/// 增强的 Prometheus 导出器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrometheusConfig {
    /// 是否启用 Prometheus 导出
    pub enabled: bool,
    /// HTTP 服务器监听端口
    pub port: u16,
    /// 指标路径
    pub path: String,
    /// 是否包含时间戳
    pub include_timestamp: bool,
    /// 指标过期时间（秒）
    pub metric_ttl: u64,
    /// 最大指标数量
    pub max_metrics: usize,
    /// 采样率（0.0-1.0）
    pub sampling_rate: f64,
    /// 是否启用指标压缩
    pub enable_compression: bool,
    /// 全局标签
    pub global_labels: HashMap<String, String>,
}

impl Default for PrometheusConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            port: 9090,
            path: "/metrics".to_string(),
            include_timestamp: true,
            metric_ttl: 3600, // 1小时
            max_metrics: 10000,
            sampling_rate: 1.0, // 不采样
            enable_compression: true,
            global_labels: HashMap::new(),
        }
    }
}

/// 增强的 Prometheus 导出器
pub struct EnhancedPrometheusExporter {
    collector: Arc<dyn MetricsCollector>,
    config: PrometheusConfig,
    custom_collectors: Arc<RwLock<HashMap<String, Arc<dyn CustomCollector>>>>,
    histogram_buckets: Arc<RwLock<HashMap<String, Vec<f64>>>>,
    metric_cache: Arc<RwLock<HashMap<String, CachedMetric>>>,
}

/// 缓存的指标
#[derive(Debug, Clone)]
struct CachedMetric {
    data: String,
    timestamp: SystemTime,
    ttl: Duration,
}

/// 自定义指标收集器接口
#[async_trait]
pub trait CustomCollector: Send + Sync {
    /// 收集器名称
    fn name(&self) -> &str;
    
    /// 描述收集器提供的指标
    fn describe(&self) -> Vec<MetricDescriptor>;
    
    /// 收集指标数据
    async fn collect(&self) -> ServiceResult<Vec<MetricFamily>>;
    
    /// 是否启用
    fn is_enabled(&self) -> bool {
        true
    }
}

/// 指标描述符
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricDescriptor {
    pub name: String,
    pub help: String,
    pub metric_type: MetricType,
    pub labels: Vec<String>,
}

impl EnhancedPrometheusExporter {
    /// 创建新的增强 Prometheus 导出器
    pub fn new(collector: Arc<dyn MetricsCollector>, config: PrometheusConfig) -> Self {
        Self {
            collector,
            config,
            custom_collectors: Arc::new(RwLock::new(HashMap::new())),
            histogram_buckets: Arc::new(RwLock::new(HashMap::new())),
            metric_cache: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// 注册自定义收集器
    pub async fn register_collector(&self, collector: Arc<dyn CustomCollector>) -> ServiceResult<()> {
        let name = collector.name().to_string();
        let mut collectors = self.custom_collectors.write().await;
        collectors.insert(name.clone(), collector);
        info!("Registered custom collector: {}", name);
        Ok(())
    }

    /// 设置直方图桶
    pub async fn set_histogram_buckets(&self, metric_name: &str, buckets: Vec<f64>) -> ServiceResult<()> {
        let mut histogram_buckets = self.histogram_buckets.write().await;
        histogram_buckets.insert(metric_name.to_string(), buckets);
        debug!("Set histogram buckets for metric: {}", metric_name);
        Ok(())
    }

    /// 导出所有指标为 Prometheus 格式
    pub async fn export(&self) -> ServiceResult<String> {
        let cache_key = "all_metrics".to_string();
        
        // 检查缓存
        if let Some(cached) = self.get_cached_metric(&cache_key).await? {
            return Ok(cached);
        }

        let mut output = String::new();
        
        // 添加全局信息
        self.write_global_info(&mut output)?;
        
        // 收集基础指标
        let metric_families = self.collector.gather().await?;
        for family in metric_families {
            self.write_metric_family(&mut output, &family).await?;
        }
        
        // 收集自定义指标
        let custom_collectors = self.custom_collectors.read().await;
        for collector in custom_collectors.values() {
            if collector.is_enabled() {
                match collector.collect().await {
                    Ok(families) => {
                        for family in families {
                            self.write_metric_family(&mut output, &family).await?;
                        }
                    }
                    Err(e) => {
                        warn!("Failed to collect metrics from {}: {}", collector.name(), e);
                    }
                }
            }
        }
        
        // 缓存结果
        self.cache_metric(cache_key, output.clone(), Duration::from_secs(self.config.metric_ttl)).await?;
        
        Ok(output)
    }

    /// 导出指定指标族
    pub async fn export_family(&self, family_name: &str) -> ServiceResult<String> {
        let cache_key = format!("family_{}", family_name);
        
        if let Some(cached) = self.get_cached_metric(&cache_key).await? {
            return Ok(cached);
        }

        let metric_families = self.collector.gather().await?;
        let mut output = String::new();
        
        for family in metric_families {
            if family.name == family_name {
                self.write_metric_family(&mut output, &family).await?;
                break;
            }
        }
        
        self.cache_metric(cache_key, output.clone(), Duration::from_secs(300)).await?;
        Ok(output)
    }

    /// 获取指标统计信息
    pub async fn get_metrics_stats(&self) -> ServiceResult<MetricsStats> {
        let metric_families = self.collector.gather().await?;
        let custom_collectors = self.custom_collectors.read().await;
        
        let mut total_metrics = 0;
        let mut total_samples = 0;
        let mut metric_types = HashMap::new();
        
        for family in &metric_families {
            total_metrics += 1;
            total_samples += family.metrics.len();
            *metric_types.entry(family.metric_type.clone()).or_insert(0) += 1;
        }
        
        Ok(MetricsStats {
            total_metric_families: total_metrics,
            total_samples,
            custom_collectors: custom_collectors.len(),
            metric_types,
            cache_size: self.metric_cache.read().await.len(),
        })
    }

    /// 清理过期缓存
    pub async fn cleanup_cache(&self) -> ServiceResult<()> {
        let mut cache = self.metric_cache.write().await;
        let now = SystemTime::now();
        
        let expired_keys: Vec<String> = cache
            .iter()
            .filter(|(_, cached)| {
                now.duration_since(cached.timestamp).unwrap_or_default() > cached.ttl
            })
            .map(|(key, _)| key.clone())
            .collect();
        
        for key in expired_keys {
            cache.remove(&key);
        }
        
        debug!("Cleaned up {} expired cache entries", cache.len());
        Ok(())
    }

    /// 创建 HTTP 路由器
    pub fn create_router(self: Arc<Self>) -> Router {
        Router::new()
            .route(&self.config.path, get(metrics_handler))
            .route(&format!("{}/stats", self.config.path), get(stats_handler))
            .with_state(self)
    }

    /// 启动 HTTP 服务器
    pub async fn start_server(self: Arc<Self>) -> ServiceResult<()> {
        if !self.config.enabled {
            info!("Prometheus exporter is disabled");
            return Ok(());
        }

        let router = self.clone().create_router();
        let addr = format!("0.0.0.0:{}", self.config.port);
        
        info!("Starting Prometheus metrics server on {}{}", addr, self.config.path);
        
        let listener = tokio::net::TcpListener::bind(&addr).await
            .map_err(|e| ServiceError::NetworkError(format!("Failed to bind to {}: {}", addr, e)))?;
            
        axum::serve(listener, router).await
            .map_err(|e| ServiceError::NetworkError(format!("Server error: {}", e)))?;
            
        Ok(())
    }

    // 私有辅助方法

    async fn get_cached_metric(&self, key: &str) -> ServiceResult<Option<String>> {
        let cache = self.metric_cache.read().await;
        if let Some(cached) = cache.get(key) {
            let elapsed = SystemTime::now().duration_since(cached.timestamp).unwrap_or_default();
            if elapsed < cached.ttl {
                return Ok(Some(cached.data.clone()));
            }
        }
        Ok(None)
    }

    async fn cache_metric(&self, key: String, data: String, ttl: Duration) -> ServiceResult<()> {
        let mut cache = self.metric_cache.write().await;
        
        // 限制缓存大小
        if cache.len() >= 1000 {
            // 移除最旧的条目
            if let Some((oldest_key, _)) = cache
                .iter()
                .min_by_key(|(_, cached)| cached.timestamp)
                .map(|(k, v)| (k.clone(), v.clone()))
            {
                cache.remove(&oldest_key);
            }
        }
        
        cache.insert(key, CachedMetric {
            data,
            timestamp: SystemTime::now(),
            ttl,
        });
        
        Ok(())
    }

    fn write_global_info(&self, output: &mut String) -> ServiceResult<()> {
        // 添加全局信息注释
        writeln!(output, "# RustCloud Metrics Export")
            .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
        
        writeln!(output, "# Timestamp: {}", 
            SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs())
            .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
        
        if !self.config.global_labels.is_empty() {
            writeln!(output, "# Global labels: {}", format_labels(&self.config.global_labels))
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
        }
        
        writeln!(output)
            .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
        
        Ok(())
    }

    async fn write_metric_family(&self, output: &mut String, family: &MetricFamily) -> ServiceResult<()> {
        if family.metrics.is_empty() {
            return Ok(());
        }

        // 写入 HELP 注释
        if !family.help.is_empty() {
            writeln!(output, "# HELP {} {}", family.name, escape_help(&family.help))
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
        }

        // 写入 TYPE 注释
        let prometheus_type = match family.metric_type {
            MetricType::Counter => "counter",
            MetricType::Gauge => "gauge", 
            MetricType::Histogram => "histogram",
            MetricType::Summary => "summary",
        };
        writeln!(output, "# TYPE {} {}", family.name, prometheus_type)
            .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;

        // 应用采样
        let metrics = if self.config.sampling_rate < 1.0 {
            self.sample_metrics(&family.metrics).await
        } else {
            family.metrics.clone()
        };

        // 写入指标数据
        for metric in &metrics {
            self.write_metric(output, metric).await?;
        }

        writeln!(output)
            .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;

        Ok(())
    }

    async fn write_metric(&self, output: &mut String, metric: &Metric) -> ServiceResult<()> {
        let mut labels = metric.labels.clone();
        
        // 添加全局标签
        for (key, value) in &self.config.global_labels {
            labels.entry(key.clone()).or_insert_with(|| value.clone());
        }

        let timestamp = if self.config.include_timestamp {
            format!(" {}", 
                metric.timestamp.duration_since(UNIX_EPOCH)
                    .unwrap_or_default()
                    .as_millis())
        } else {
            String::new()
        };

        match &metric.value {
            MetricValue::Counter(value) => {
                writeln!(
                    output,
                    "{}{}{}{}",
                    metric.name,
                    format_labels(&labels),
                    value,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
            MetricValue::Gauge(value) => {
                writeln!(
                    output,
                    "{}{}{}{}",
                    metric.name,
                    format_labels(&labels),
                    value,
                    timestamp
                )
                .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
            MetricValue::Histogram { count, sum, buckets } => {
                // 写入每个桶
                for (upper_bound, bucket_count) in buckets {
                    let mut bucket_labels = labels.clone();
                    bucket_labels.insert("le".to_string(), format_float(*upper_bound));
                    writeln!(
                        output,
                        "{}_bucket{} {}{}",
                        metric.name,
                        format_labels(&bucket_labels),
                        bucket_count,
                        timestamp
                    )
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
                }

                // 写入总数和总和
                writeln!(output, "{}_count{} {}{}", metric.name, format_labels(&labels), count, timestamp)
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
                writeln!(output, "{}_sum{} {}{}", metric.name, format_labels(&labels), sum, timestamp)
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
            MetricValue::Summary { count, sum, quantiles } => {
                // 写入分位数
                for (quantile, value) in quantiles {
                    let mut quantile_labels = labels.clone();
                    quantile_labels.insert("quantile".to_string(), quantile.to_string());
                    writeln!(
                        output,
                        "{}{} {}{}",
                        metric.name,
                        format_labels(&quantile_labels),
                        value,
                        timestamp
                    )
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
                }

                // 写入总数和总和
                writeln!(output, "{}_count{} {}{}", metric.name, format_labels(&labels), count, timestamp)
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
                writeln!(output, "{}_sum{} {}{}", metric.name, format_labels(&labels), sum, timestamp)
                    .map_err(|e| ServiceError::MetricsError(format!("Write error: {}", e)))?;
            }
        }

        Ok(())
    }

    async fn sample_metrics(&self, metrics: &[Metric]) -> Vec<Metric> {
        if self.config.sampling_rate >= 1.0 {
            return metrics.to_vec();
        }

        // 简单的随机采样
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};

        metrics
            .iter()
            .filter(|metric| {
                let mut hasher = DefaultHasher::new();
                metric.name.hash(&mut hasher);
                // 对标签进行字符串化后再 hash
                let labels_str = format!("{:?}", metric.labels);
                labels_str.hash(&mut hasher);
                let hash = hasher.finish();
                (hash as f64 / u64::MAX as f64) < self.config.sampling_rate
            })
            .cloned()
            .collect()
    }
}

/// 指标统计信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsStats {
    pub total_metric_families: usize,
    pub total_samples: usize,
    pub custom_collectors: usize,
    pub metric_types: HashMap<MetricType, usize>,
    pub cache_size: usize,
}

// HTTP 处理函数

async fn metrics_handler(
    State(exporter): State<Arc<EnhancedPrometheusExporter>>,
) -> Result<Response, StatusCode> {
    match exporter.export().await {
        Ok(metrics) => {
            let mut headers = HeaderMap::new();
            headers.insert(
                "content-type",
                HeaderValue::from_static("text/plain; version=0.0.4; charset=utf-8"),
            );
            
            if exporter.config.enable_compression {
                // TODO: 添加 gzip 压缩支持
            }
            
            Ok((headers, metrics).into_response())
        }
        Err(e) => {
            error!("Failed to export metrics: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

async fn stats_handler(
    State(exporter): State<Arc<EnhancedPrometheusExporter>>,
) -> Result<axum::Json<MetricsStats>, StatusCode> {
    match exporter.get_metrics_stats().await {
        Ok(stats) => Ok(axum::Json(stats)),
        Err(e) => {
            error!("Failed to get metrics stats: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

// 辅助函数

fn format_labels(labels: &Labels) -> String {
    if labels.is_empty() {
        return String::new();
    }

    let mut label_pairs: Vec<_> = labels.iter().collect();
    label_pairs.sort_by_key(|&(k, _)| k);

    let mut result = String::from("{");
    for (i, (key, value)) in label_pairs.iter().enumerate() {
        if i > 0 {
            result.push(',');
        }
        result.push_str(&format!("{}=\"{}\"", key, escape_label_value(value)));
    }
    result.push('}');
    result
}

fn escape_help(help: &str) -> String {
    help.replace('\\', "\\\\").replace('\n', "\\n")
}

fn escape_label_value(value: &str) -> String {
    value
        .replace('\\', "\\\\")
        .replace('"', "\\\"")
        .replace('\n', "\\n")
}

fn format_float(value: f64) -> String {
    if value == f64::INFINITY {
        "+Inf".to_string()
    } else if value == f64::NEG_INFINITY {
        "-Inf".to_string()
    } else if value.is_nan() {
        "NaN".to_string()
    } else {
        value.to_string()
    }
}

/// 系统指标收集器示例（重复定义！）
/// WARNING: 这是重复定义，已经在 prometheus.rs 中定义了 SystemMetricsCollector
/// TODO: 重构此实现，避免重复定义或重命名为 EnhancedSystemMetricsCollector
/// 
/// 注意：prometheus.rs 模块已经提供了 SystemMetricsCollector 实现
/// 此版本实现了 CustomCollector trait，而 prometheus.rs 版本实现了 PrometheusMetric trait
/// 建议将两者合并为一个统一的实现
#[deprecated(note = "存在重复定义，建议使用 prometheus.rs 中的 SystemMetricsCollector 或重命名此实现")]
pub struct SystemMetricsCollector {
    enabled: bool,
}

#[allow(deprecated)]
impl SystemMetricsCollector {
    pub fn new() -> Self {
        Self { enabled: true }
    }
}

#[async_trait]
#[allow(deprecated)]
impl CustomCollector for SystemMetricsCollector {
    fn name(&self) -> &str {
        "system"
    }

    fn describe(&self) -> Vec<MetricDescriptor> {
        vec![
            MetricDescriptor {
                name: "rustcloud_process_cpu_usage".to_string(),
                help: "Process CPU usage percentage".to_string(),
                metric_type: MetricType::Gauge,
                labels: vec!["process".to_string()],
            },
            MetricDescriptor {
                name: "rustcloud_process_memory_bytes".to_string(),
                help: "Process memory usage in bytes".to_string(),
                metric_type: MetricType::Gauge,
                labels: vec!["type".to_string()],
            },
        ]
    }

    async fn collect(&self) -> ServiceResult<Vec<MetricFamily>> {
        if !self.enabled {
            return Ok(vec![]);
        }

        let mut families = Vec::new();

        // CPU 使用率 (模拟数据)
        let cpu_family = MetricFamily {
            name: "rustcloud_process_cpu_usage".to_string(),
            help: "Process CPU usage percentage".to_string(),
            metric_type: MetricType::Gauge,
            metrics: vec![Metric {
                name: "rustcloud_process_cpu_usage".to_string(),
                help: "Process CPU usage percentage".to_string(),
                metric_type: MetricType::Gauge,
                value: MetricValue::Gauge(15.5), // 模拟 15.5% CPU 使用率
                labels: {
                    let mut labels = HashMap::new();
                    labels.insert("process".to_string(), "rustcloud".to_string());
                    labels
                },
                timestamp: SystemTime::now(),
            }],
        };
        families.push(cpu_family);

        // 内存使用情况
        let memory_family = MetricFamily {
            name: "rustcloud_process_memory_bytes".to_string(),
            help: "Process memory usage in bytes".to_string(),
            metric_type: MetricType::Gauge,
            metrics: vec![
                Metric {
                    name: "rustcloud_process_memory_bytes".to_string(),
                    help: "Process memory usage in bytes".to_string(),
                    metric_type: MetricType::Gauge,
                    value: MetricValue::Gauge(134217728.0), // 128MB
                    labels: {
                        let mut labels = HashMap::new();
                        labels.insert("type".to_string(), "resident".to_string());
                        labels
                    },
                    timestamp: SystemTime::now(),
                },
                Metric {
                    name: "rustcloud_process_memory_bytes".to_string(),
                    help: "Process memory usage in bytes".to_string(),
                    metric_type: MetricType::Gauge,
                    value: MetricValue::Gauge(268435456.0), // 256MB
                    labels: {
                        let mut labels = HashMap::new();
                        labels.insert("type".to_string(), "virtual".to_string());
                        labels
                    },
                    timestamp: SystemTime::now(),
                },
            ],
        };
        families.push(memory_family);

        Ok(families)
    }

    fn is_enabled(&self) -> bool {
        self.enabled
    }
}